package com.dp.util;

import com.alibaba.fastjson.JSON;
import org.bouncycastle.crypto.engines.AESFastEngine;
import org.bouncycastle.crypto.modes.GCMBlockCipher;
import org.bouncycastle.crypto.params.AEADParameters;
import org.bouncycastle.crypto.params.KeyParameter;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.*;

/**
 * @ClassName AesGcm256Util
 * @Description:AES-GCM-256 工具类  加解密方法中已调用 Base64 方法
 * @Auther: 田英杰
 * @Date: 2023/03/30 20:42
 * @Version: 1.0.0.0
 */
public class AesGcm256Util {
    private static final SecureRandom SECURE_RANDOM = new SecureRandom();
    public static final int NONCE_BIT_SIZE = 128;
    public static final int MAC_BIT_SIZE = 128;
    public static final int KEY_BIT_SIZE = 256;

    public static final String AES_KEY = "D5AA36E6795B488A992A9E67151BC90E";
    public static final String AES_IV = "7845EA78F74C4D728996C6CF46C669B0";

    private AesGcm256Util() {
    }

    /**
     * 创建密钥
     *
     * @return 密钥
     */
    public static byte[] key() {
        byte[] key = new byte[KEY_BIT_SIZE / 8];
        SECURE_RANDOM.nextBytes(key);

        return key;
    }

    /**
     * 创建向量
     *
     * @return 向量
     */
    public static byte[] iv() {
        byte[] iv = new byte[NONCE_BIT_SIZE / 8];
        SECURE_RANDOM.nextBytes(iv);

        return iv;
    }

    /**
     * 编码
     *
     * @param hexStr 文本
     * @return 字节数组
     */
    public static byte[] hexToByte(String hexStr) {
        int len = hexStr.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexStr.charAt(i), 16) << 4) +
                    Character.digit(hexStr.charAt(i + 1), 16));
        }

        return data;
    }

    /**
     * 转为十六进制
     *
     * @param data 字节数组
     * @return 转换结果
     */
    public static String toHex(byte[] data) {
        StringBuilder ret = new StringBuilder();
        for (byte datum : data) {
            String hex = Integer.toHexString(datum & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            ret.append(hex.toUpperCase());
        }

        return ret.toString();
    }

    /**
     * 加密
     *
     * @param plainText 明文文本
     * @return 加密字符串
     */
    public static String encrypt(String plainText) {
        String sr;
        try {
            byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
            GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
            AEADParameters parameters = new AEADParameters(new KeyParameter(AesGcm256Util.hexToByte(AES_KEY)), MAC_BIT_SIZE, AesGcm256Util.hexToByte(AES_IV), null);
            cipher.init(true, parameters);
            byte[] encryptedBytes = new byte[cipher.getOutputSize(plainBytes.length)];
            int retLen = cipher.processBytes(plainBytes, 0, plainBytes.length, encryptedBytes, 0);
            cipher.doFinal(encryptedBytes, retLen);
            sr = Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception ex) {
            throw new RuntimeException(ex.getMessage());
        }

        return sr;
    }


    public static String decrypt(String encryptedText) {
        String sr;
        try {
            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
            GCMBlockCipher cipher = new GCMBlockCipher(new AESFastEngine());
            AEADParameters parameters = new AEADParameters(new KeyParameter(AesGcm256Util.hexToByte(AES_KEY)), MAC_BIT_SIZE, AesGcm256Util.hexToByte(AES_IV), null);
            cipher.init(false, parameters);
            byte[] plainBytes = new byte[cipher.getOutputSize(encryptedBytes.length)];
            int retLen = cipher.processBytes(encryptedBytes, 0, encryptedBytes.length, plainBytes, 0);
            cipher.doFinal(plainBytes, retLen);
            sr = new String(plainBytes, StandardCharsets.UTF_8);
        } catch (Exception ex) {
            throw new RuntimeException(ex.getMessage());
        }

        return sr;
    }

    public static void main(String[] args) throws Exception {
        List<Map<String,Object>> list = new ArrayList<>();
        try {
            String uuid = ESN.getUUID();
            String uuid1 = ESN.getUUID();
            Map<String, Object> map = new HashMap<>();
            List<String> list1 = new ArrayList<>();
            List<String> list2 = new ArrayList<>();
            List<String> list3 = new ArrayList<>();
            list1.add("0fdcec73-f7c1-40b3-9207-445f73d371eb");
            list2.add("乙炔气柜");
            map.put("stationId","0253a447-9a7c-4829-a9c5-2a937451ea23");
            map.put("stationName","巡检一");
            map.put("latitude","423.643");
            map.put("longitude","6544.874894");
              map.put("equipmentIds",list1);
              map.put("btMacCode","546");
               map.put("btName","蓝一");
              map.put("nfcNo","N85646");
              map.put("radius","88");
            map.put("hazardId",list2);
            map.put("departmentId","40c89aed-6a4c-4550-a285-e7d6c6ad17f0");
            map.put("departmentName","制冷车间");
            map.put("deleted","0");
            map.put("createDate","2022-12-27 17:21:09");
            map.put("createBy","admin");
            map.put("updateDate","2022-12-27 17:21:09");
            map.put("updateBy","admin");
            List<Map<String,Object>> list4 = new ArrayList<>();
            Map<String,Object> map1 = new HashMap<>();
            map1.put("equipmentName","设备一");
            map1.put("checkName","检查名称");
            map1.put("checkType","1");
            list4.add(map1);
            map.put("check",list4);




            list.add(map);
            String s = JSON.toJSONString(list);
            System.err.println("原数据"+s);
            String AES_KEY = "D5AA36E6795B488A992A9E67151BC90E";
            String AES_IV = "7845EA78F74C4D728996C6CF46C669B0";

            String encrypt = AesGcm256Util.encrypt(s);
//            JSONObject jsonObject = JSONUtil1.SUCCESSJson(encrypt);
            System.out.println("加密"+encrypt);
            String str = "";
            String resultStr = AesGcm256Util.decrypt(str);
            System.err.println("解密"+resultStr);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
